﻿using System;
using System.ComponentModel;
using SwiftMVVM.ViewModel;
using SwiftMVVM.ChangeTracking;
using System.ComponentModel.DataAnnotations;

namespace SampleApplication.Data
{
    /// <summary>
    /// Represents a order, from a bakery, yea... 
    /// Really this is just a simple class to help present
    /// grid sorting on strings, numbers, and dates.
    /// The data is stored in tblOrders in a SQL Server DB
    /// </summary>
    [Description("Order")]
    public abstract class Order : DependentBindingObject, IDataErrorInfo
    {
        /// <summary>
        /// OrderId is our primary Key in tblOrders
        /// </summary>
        [Description("Order ID")]
        public int ? OrderID { get; set; }

        /// <summary>
        /// Reference to the parent OrderManager. I use this for easy
        /// access to the OrderManager from any given order. 
        /// </summary>
        public OrderManager Parent { get; private set; }

        /// <summary>
        /// The Price property is auto calculated when the weight on our
        /// order is changed or when the PricePerPound property on our
        /// parent OrderManager is changed. Or if the PriceMultiplier is changed.
        /// DependsOn attributes can only be used on ReadOnly properties.
        /// We've also marked the TableFieldMapping as OneWayToSource because 
        /// we only want the value to go to the DB and not back.
        /// </summary>
        [TrackChanges]
        [DependsOn("Weight")]
        [DependsOn("Parent", "PricePerPound")]
        [DependsOn("Parent", "PriceMultiplier")]
        public decimal Price { get { return this.Weight * Parent.PricePerPound * ((int)Parent.PriceMultiplier); } }

        /// <summary>
        /// The name of the order, we are tracking all changes to the name of the order
        /// </summary>
        [TrackChanges]
        [NotificationProperty]
        public virtual string Name { get; set; }

        /// <summary>
        /// The weight of the order, we are tracking all changes to the name of the order
        /// </summary>
        [TrackChanges]
        [NotificationProperty]
        [Range(5,15)]
        public virtual decimal Weight { get; set; }

        /// <summary>
        /// Represents the state this set of orders is going to, 
        /// we are tracking all changes to the name of the cooki
        /// </summary>
        [TrackChanges]
        [NotificationProperty]
        public virtual States DestinationState { get; set; }

        /// <summary>
        /// The date that the order was baked. This is readonly and cannot change
        /// Therefore no need to track it.
        /// </summary>
        [TrackChanges]
        [NotificationProperty]
        public virtual DateTime DateBaked { get; set; }

        /// <summary>
        /// Bakes a new order
        /// </summary>
        /// <param name="name">The name of the cookies in the order</param>
        /// <param name="weight">The weight of the order</param>
        /// <param name="dateBaked">The date the order was baked</param>
        public Order(OrderManager parent, int? orderID, string name, int weight, DateTime dateBaked, States destinationState)
            : base()
        {
            this.Parent = parent;
            this.OrderID = orderID;
            this.Name = name;
            this.Weight = weight;
            this.DateBaked = dateBaked;
            this.DestinationState = destinationState;
        }

        /// <summary>
        /// Gets an error message indicating what is wrong with this object. 
        /// </summary>
        string IDataErrorInfo.Error { get { return DataErrorInfoSupport.GetError(this); } }

        /// <summary>
        /// Gets the error message for the property with the given name. 
        /// </summary>
        /// <param name="memberName">The name of the property whose error message to get. </param>
        /// <returns>The error message for the property. The default is an empty string ("").</returns>
        string IDataErrorInfo.this[string memberName] { get { return DataErrorInfoSupport.GetError(this, memberName); } }
    }
}
